package main

import (
	"context"
	"fmt"
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/base"
	"github.com/alibaba/sentinel-golang/core/config"
	"github.com/alibaba/sentinel-golang/core/flow"
	"github.com/alibaba/sentinel-golang/logging"
	"github.com/gin-gonic/gin"
	"go-sentinel-demo/proto"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"net/http"

	"log"
)

func main() {
	InitSentinel()
	r := gin.Default()
	//r.Use(sentinelPlugin.SentinelMiddleware())

	r.GET("/index", func(c *gin.Context) {
		// ****限流开始****
		e, b := sentinel.Entry("lqz-test", sentinel.WithTrafficType(base.Inbound))
		if b != nil {
			// 返回给前端，超过了qps
			fmt.Println("失败")
			c.JSON(http.StatusTooManyRequests, gin.H{"msg": "请求过快,请稍后再试"})
			return
		}
		e.Exit() // 不要忘了加它
		// ****限流结束****

		// 第一步：连接服务端
		conn, err := grpc.Dial("127.0.0.1:50052", grpc.WithTransportCredentials(insecure.NewCredentials()))
		if err != nil {
			c.JSON(200, "连接服务异常")
		}
		defer conn.Close()

		// 第二步：创建客户端调用
		client := proto.NewGreeterClient(conn)
		resp, err := client.SayHello(context.Background(), &proto.HelloRequest{
			Name: "lqz",
			Age:  19,
		})

		if err != nil {
			c.JSON(200, "服务器错误")
		}
		c.JSON(200, resp.Reply)
	})

	r.Run()
}

func InitSentinel() {
	conf := config.NewDefaultConfig()
	// for testing, logging output to console
	conf.Sentinel.Log.Logger = logging.NewConsoleLogger()
	//方式一： 通过配置文件创建
	err := sentinel.InitWithConfig(conf)
	//方式二： 通过默认创建
	//err :sentinel.InitDefault()
	if err != nil {
		fmt.Println("sss")
		log.Fatal(err)
	}

	// TokenCalculateStrategy配置flow.Direct，Threshold配置1，StatIntervalInMs配置100，表示1s钟1个流量
	_, err = flow.LoadRules([]*flow.Rule{{
		Resource:               "lqz-test",      //资源名，即规则的作用目标
		TokenCalculateStrategy: flow.Direct,     //当前流量控制器的Token计算策略。Direct表示直接使用字段 Threshold 作为阈值；WarmUp表示使用预热方式计算Token的阈值,三种方式
		ControlBehavior:        flow.Throttling, //Throttling表示匀速排队
		Threshold:              1,               //表示流控阈值；如果字段 StatIntervalInMs 是1000(也就是1秒)，那么Threshold就表示QPS，流量控制器也就会依据资源的QPS来做流控
		StatIntervalInMs:       1000,            //规则对应的流量控制器的独立统计结构的统计周期。如果StatIntervalInMs是1000，也就是统计QPS
	}})

	if err != nil {
		log.Fatalf("Unexpected error: %+v", err)
		return
	}
}
